use std::time::Duration;

use async_trait::async_trait;
use base_data::channel::EndReason;
use tools::{utils::gen_id::get_now_duration, ResultNull};
use tracing::{info, warn};

use crate::{
	business::{
		bus_trait::Business,
		inbound400::{
			bus_all_call::SaveCalleds,
			context::{BusinessState, InboundRunContext},
		},
	},
	db::persistence::InboundDBO,
	link_to_sip::{answer, play_sound_file_to_caller, record_sound},
};

#[derive(Debug, Clone)]
pub struct LeaveMessage;

// {
// 	pub node_id: i32,
// 	pub parent_id: i32,
// 	start_time: Option<OffsetDateTime>,
// }

#[async_trait]
impl Business for LeaveMessage {
	type C = InboundRunContext;

	async fn play_back_stop(&self, context: &mut InboundRunContext,_channel_id:u32) -> ResultNull {
		context.start_charge();
		context.start_talk();

		let rec_file_name = format!("{}.wav", &context.ch_call_id);
		record_sound(context.caller_channel(), &rec_file_name)?;
		context.rec_file_name = Some(rec_file_name);

		Ok(())
	}

	async fn check(&self, context: &mut InboundRunContext) -> ResultNull {
		//最多5分钟留言时间
		if get_now_duration() > context.check_time + Duration::from_secs(5 * 60) {
			SaveCalleds::remove_called(&context.now_called_num()).await;
			context.business_state = BusinessState::End(EndReason::TalkNocallerd);
		}

		Ok(())
	}

	async fn hangup(
		&self,
		context: &mut Self::C,
		_channel_id: u32,
		_reason: EndReason,
	) -> ResultNull {
		info!("语音留言,收到挂断消息");

		//收到挂断消息，同时清除全局呼叫记录
		SaveCalleds::remove_called(&context.now_called_num()).await;

		context.business_state = BusinessState::End(EndReason::LeaveMessageOver);

		Ok(())
	}

	async fn closeing(&self, context: &mut InboundRunContext) -> ResultNull {
		if let Some(name) = context.rec_file_name.as_ref() {
			InboundDBO::update_record_file(&context.target(), name).await?;
		} else {
			warn!("没有记录录音文件...留言应该有的");
		}

		InboundDBO::record_and_charge(
			context,
			"",
			&context.rec_file_name,
			EndReason::TalkNocallerd,
			context.node_info.node_id,
			"",
			"",
		)
		.await?;

		Ok(())
	}

	async fn start_call(&self, context: &mut InboundRunContext) -> ResultNull {
		if !context.is_answered_caller() {
			answer(context.caller_channel())?;
		}

		let path = InboundDBO::get_leave_msg_path(
			&context.target(),
			context.node_info.node_id,
			context.node_is_empty(),
		)
		.await?;
		play_sound_file_to_caller(context.caller_channel(), &path)?;
		context.check_time = get_now_duration();
		Ok(())
	}
}
